package cn.tedu.vue_master.security;

import cn.tedu.vue_master.pojo.Constants;
import cn.tedu.vue_master.pojo.user.UserInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 *     单点登录过滤器
 * </p>
 */
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SSOFilter extends OncePerRequestFilter {
    private final StringRedisTemplate stringRedisTemplate;

    private final JwtTokenUtils jwtTokenUtils;

    private static final String REQUEST_HEADER_AUTHORIZATION = "Authorization";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 查看所有到达当前系统请求是否有认证信息，有则存放context的数据
        // 获取AUTHORIZATION头
        String authHeader = request.getHeader(REQUEST_HEADER_AUTHORIZATION);
        if (authHeader != null && authHeader.startsWith(Constants.JWTTOKENHEAD)) {
            String authToken = authHeader.substring(Constants.JWTTOKENHEAD.length());
            log.debug("authToken = {}",authToken);

            //从redis验证是否已经退出登录
            //写入redis 锁住 这里采用list分日期存储,方便后续定时清理
            String lockedTokenList="token_list_.lock";
            Boolean member = stringRedisTemplate.boundSetOps(lockedTokenList).isMember(authToken);
            if(member){
                log.info("从redis拿到登录的token:"+authToken);
                filterChain.doFilter(request, response);
                return;
            }
            UserInfo userInfo = jwtTokenUtils.getMyUserDetails(authToken);
            UsernamePasswordAuthenticationToken authentication=null;
            if (userInfo != null) {
                log.debug("从jwt中解析到的userInfo = {}",userInfo);
                authentication = new UsernamePasswordAuthenticationToken(
                        userInfo.getUserName(),
                        userInfo,
                        userInfo.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
            }
        }

        filterChain.doFilter(request, response);
    }
}
